
package cn.tang.tframe.dynconfig;

import cn.tang.tframe.common.base.MainConfigLoader;
import cn.tang.tframe.dynconfig.domain.Configuration;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

/**
 * DynConfigProcessor 工厂类
 *
 * @author tanghc
 */
public class DynConfigRegister {

	static Logger logger =
		LoggerFactory.getLogger(DynConfigRegister.class);

	private static ReentrantLock lock = new ReentrantLock();

	private static class DynConfigRegisterHolder {

		private static DynConfigRegister instance =
			new DynConfigRegister();
	}

	private DynConfigRegister() {
	}

	private static ConcurrentMap<String, IDynConfigProcessor> dynConfigProcessorMap =
		Maps.newConcurrentMap();

	/**
	 * 获取DynConfigProcessor实例(单例)
	 * 
	 * @return
	 */
	public static DynConfigRegister getInstance() {

		return DynConfigRegisterHolder.instance;
	}

	/**
	 * 对于同一个坐标配置信息只能创建一次
	 * 
	 * @return
	 */
	public IDynConfigProcessor buildOnce(
		final String group, final String dataId,
		IDynConfigProcessor dynConfigProcessor) {

		return buildOnce(
			MainConfigLoader.getInstance().getProductCode(),
			MainConfigLoader.getInstance().getAppCode(), group,
			dataId, dynConfigProcessor);
	}


	public IDynConfigProcessor buildOnce(
		final String productCode, final String appName, final String group,
		final String dataId, final IDynConfigProcessor dynConfigProcessor) {

		DynConfigClient dynConfigClient =
				DynConfigClientFactory.getClient();
		return buildOnce(dynConfigClient,productCode,appName,group,dataId,dynConfigProcessor);
	}
	public IDynConfigProcessor buildOnce(final DynConfigClient dynConfigClient,
		final String productCode, final String appName, final String group,
		final String dataId, final IDynConfigProcessor dynConfigProcessor) {

		lock.lock();
		String key = new StringBuilder().append(productCode).append(":").append(
				appName).append(":").append(group).append(":").append(
				dataId).append(":").toString();
		try {
//			校验是否是一次创建
			if(null != dynConfigProcessorMap.get(key)){
				throw new RuntimeException("IDynConfigProcessor can only build once");
			}
//			获取参数
			String config = dynConfigClient.getConfig(
				productCode, appName, group, dataId);
			if(null != dynConfigProcessor ){
				dynConfigProcessor.procesConfig(config);
			}
//			注册动态修改参数事件
			DynConfigClientFactory.getClient().registerListeners(
					productCode, appName, group, dataId, new IChangeListener() {

					@Override
					public Executor getExecutor() {

						return Executors.newSingleThreadExecutor();
					}

					@Override
					public void receiveConfigInfo(
						final Configuration configuration) {

						getExecutor().execute(new Runnable() {

							@Override
							public void run() {

								String config = configuration.getConfig();
								if(null != dynConfigProcessor ){
									dynConfigProcessor.procesConfig(config);
								}
							}
						});
					}
				});
		}
		catch (Exception e) {
			logger.error(
				"build IDynConfigProcessor error: product={},app={},group={},dataid={}",
				productCode, appName, group, dataId, e);
		}
		finally {
			dynConfigProcessorMap.put(key,dynConfigProcessor);
			lock.unlock();
		}

		return dynConfigProcessor;
	}

}
